#ifndef __M_ONLINE_H__
#define __M_ONLINE_H__

#include "util.hpp"
#include <unordered_map>
#include <mutex>

// 该类主要实现在线用户的管理
// 在线用户有两种：1. 游戏大厅  2. 游戏房间
// 所以需要两个哈希表来管理这两个房间
// 由于是多线程，所以上面两个哈希表是共享资源，还需要一把锁来辅助进行插入和删除

// 那这两个哈希表的键值各是什么？
// 通过用户id(uid键) 管理 每个用户的websocket连接(值)

typedef websocketpp::server<websocketpp::config::asio> wsserver_t;

class online_manager
{
public:
    online_manager()
    {
        // 由于类内成员变量是自定义类型，编译器会自动调用它们的构造函数进行初始化，析构也一样
        DLOG("The initial completion of the online user management module!");
    }
    ~online_manager()
    {
    }

    // websocket连接建立的时候才会加入游戏大厅&游戏房间在线用户管理
    void enter_game_hall(uint32_t uid, wsserver_t::connection_ptr &conn)
    {
        std::unique_lock<std::mutex> lock(_mtx);
        _hall_online_user.insert(std::make_pair(uid, conn));
    }

    void enter_game_room(uint32_t uid, wsserver_t::connection_ptr &conn)
    {
        std::unique_lock<std::mutex> lock(_mtx);
        _room_online_user.insert(std::make_pair(uid, conn));
    }

    // websocket连接断开的时候，才会移除游戏大厅&游戏房间在线用户管理
    void exit_game_hall(uint32_t uid)
    {
        std::unique_lock<std::mutex> lock(_mtx);
        _hall_online_user.erase(uid);
    }

    void exit_game_room(uint32_t uid)
    {
        std::unique_lock<std::mutex> lock(_mtx);
        _room_online_user.erase(uid);
    }

    // 判断当前指定用户是否在游戏大厅/游戏房间
    bool is_in_game_hall(uint32_t uid)
    {
        std::unique_lock<std::mutex> lock(_mtx);
        auto iter = _hall_online_user.find(uid);

        if (iter == _hall_online_user.end())
            return false;
        return true;
    }

    bool is_in_game_room(uint32_t uid)
    {
        std::unique_lock<std::mutex> lock(_mtx);
        auto iter = _room_online_user.find(uid);

        if (iter == _room_online_user.end())
            return false;
        return true;
    }

    // 通过用户ID在游戏大厅/游戏房间用户管理中获取对应的通信连接
    wsserver_t::connection_ptr get_conn_from_hall(uint32_t uid)
    {
        std::unique_lock<std::mutex> lock(_mtx);
        auto iter = _hall_online_user.find(uid);

        // 如果找不到，返回一个空的connection_ptr
        if (iter == _hall_online_user.end())
            return wsserver_t::connection_ptr();

        return iter->second;
    }

    wsserver_t::connection_ptr get_conn_from_room(uint32_t uid)
    {
        std::unique_lock<std::mutex> lock(_mtx);
        auto iter = _room_online_user.find(uid);

        // 如果找不到，返回一个空的connection_ptr
        if (iter == _room_online_user.end())
            return wsserver_t::connection_ptr();

        return iter->second;
    }

private:
    // 用于建立游戏大厅用户的用户ID与通信连接的关系
    std::unordered_map<uint32_t, wsserver_t::connection_ptr> _hall_online_user;

    // 用于建立游戏房间用户的用户ID与通信连接的关系
    std::unordered_map<uint32_t, wsserver_t::connection_ptr> _room_online_user;

    // 保护上方两个哈希表的访问安全问题
    std::mutex _mtx;
};

#endif